package game.Engine.Entity;

import game.MainController;
import game.Input.EventSound;
import game.display.Animation;
import game.display.Images;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

public class Magic extends Entity {

   public static enum MagicType {
      AIR(0), FIRE(1), EARTH(2), WATER(3), LIGHTNING(4);
      int num;

      MagicType(int num) {
         this.num = num;
      }

      int getNum() {
         return num;
      }

      static MagicType getTypebyNum(int num) {
         switch (num) {
         case 0:
            return AIR;
         case 1:
            return FIRE;
         case 2:
            return EARTH;
         case 3:
            return WATER;
         case 4:
            return LIGHTNING;
         default:
            return AIR;
         }
      }

      MagicType getNextType() {
         switch (this) {
         case AIR:
            return FIRE;
         case FIRE:
            return EARTH;
         case EARTH:
            return WATER;
         case WATER:
            return LIGHTNING;
         case LIGHTNING:
            return AIR;

         }
         return AIR;
      }

      MagicType getLastType() {
         switch (this) {
         case AIR:
            return LIGHTNING;
         case FIRE:
            return AIR;
         case EARTH:
            return FIRE;
         case WATER:
            return EARTH;
         case LIGHTNING:
            return WATER;

         }
         return AIR;
      }
   }

   private MagicType type;
   private transient boolean hasPlayed;
   private transient Entity source;

   public Magic(Point2D.Double source, double speed, Point2D.Double dest,
         MagicType type, Entity psource, double sdx, double sdy) {
      super(source.x, source.y, getImage(type));
      this.type = type;
      state = State.NORMAL;
      double deltaX = dest.x - source.x;
      double deltaY = dest.y - source.y;
      dx = speed * deltaX / source.distance(dest);
      dy = speed * deltaY / source.distance(dest);
      if (dx / sdx > 0) {
         dx += sdx;
      }
      if(dy / sdy > 0) {
         dy += sdy;
      }
      this.source = psource;

   }

   private void checkForCollisions() {
      if (state == State.NORMAL) {
         for (Entity e : MainController.gameEngine.entities) {
            if (collidesWith(e)) {
               handleCollision(e);
            }
         }
      }
   }

   public MagicType getType() {
      return type;
   }

   public void handleCollision(Entity e) {
      if (!((e instanceof Magic) || (e instanceof Mouse) || (e instanceof PowerUp) || (e instanceof AlienSpawn))) {
         if (source instanceof Player) {
            if (!(e == source)) {
               e.hitBy(this);
               e.setHitBy(source);
               die();
            }
         } else {
            if (!(e instanceof Alien)) {
               e.hitBy(this);
               e.setHitBy(source);
               die();
            }
         }
      }
   }

   public boolean collidesWith(Entity t) {
      Rectangle2D.Double us = getBoundingBox();
      Rectangle2D.Double them = t.getBoundingBox();
      Rectangle2D intersect = us.createIntersection(them);
      if (intersect.getWidth() > 0.25 && intersect.getHeight() > 0.25) {
         return true;
      } else {
         return false;
      }
   }

   private static Animation getImage(MagicType type2) {
      switch (type2) {
      case FIRE:
         return Images.FIREWEAPON.image();
      case EARTH:
         return Images.EARTHWEAPON.image();
      case WATER:
         return Images.WATERWEAPON.image();
      case AIR:
         return Images.AIRWEAPON.image();
      case LIGHTNING:
         return Images.LIGHTNINGWEAPON.image();
      default:
         return Images.AIRWEAPON.image();
      }
   }

   public Animation getDyingImage() {
      switch (type) {
      case FIRE:
         return Images.REDEXPLOSION.image();
      case EARTH:
         return Images.GREENEXPLOSION.image();
      case WATER:
         return Images.BLUEEXPLOSION.image();
      case AIR:
         return Images.WHITEEXPLOSION.image();
      case LIGHTNING:
         return Images.YELLOWEXPLOSION.image();
      default:
         return Images.AIRWEAPON.image();
      }
   }
   
   public void updateImage(){
	   if(gi == null)gi = getImage(this.type);
	   else if(this.state == Entity.State.DYING)gi = getDyingImage();
		   
   }

   @Override
   public void update(long timeElapsed) {
      super.update(timeElapsed);
      move(timeElapsed);
      checkForCollisions();
      if(state == Entity.State.DYING && !hasPlayed){
    	  boolean play = false;
    	  for(Player p: MainController.gameEngine.players){
    	  double changeX = Math.abs(this.x-p.getX());
    	  double changeY = Math.abs(this.y-p.getY());
    	  if(changeX < 7 && changeY < 4) play = true;
    	  hasPlayed = true;
    	  }
    	  if(play)MainController.soundController.addEventSoundAction(EventSound.HIT);
      }
   }
   
   public void matchWith(Magic m){
		z = m.getZ();
		x = m.getX();
		y = m.getY();
		dx = m.getVelocityX();
		dy = m.getVelocityY();
		state = m.getState();
		type = m.getType();
   }
}
